
package com.hlkj.pay.app.ad.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.ad.IAdOrderCallBackService;
import com.hlkj.pay.dto.ad.AdOtherConfigDto;
import com.hlkj.pay.dto.ad.result.HlPayOrderDetailResultDto;
import com.hlkj.pay.dto.ad.result.HlRefundOrderDetailResultDto;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.enums.UserEnum;
import com.hlkj.pay.infrastructure.model.ad.AdInfoConfigDO;
import com.hlkj.pay.infrastructure.model.ad.AdPayOrderDO;
import com.hlkj.pay.infrastructure.model.ad.AdRefundOrderDO;
import com.hlkj.pay.infrastructure.model.user.UserTeleChargeOrderDO;
import com.hlkj.pay.service.ad.IAdInfoService;
import com.hlkj.pay.service.ad.IAdPayOrderService;
import com.hlkj.pay.service.ad.IAdRefundOrderService;
import com.hlkj.pay.service.user.IUserRechargeService;
import com.hlkj.pay.util.SignUtils;

import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/10/30 16:19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdOrderCallBackServiceImpl implements IAdOrderCallBackService {

    private final IAdInfoService adInfoService;

    private final IAdPayOrderService adPayOrderService;

    private final AdPayOrderHandler adPayOrderHandler;

    private final IAdRefundOrderService adRefundOrderService;

    private final IUserRechargeService userRechargeService;

    @Override
    public String orderStatusCallBack(Long adId, String accessCallBody) {
        log.info("orderStatusCallBack adId:{},accessCallBody:{}", adId, accessCallBody);
        try {
            HlPayOrderDetailResultDto hlPayOrderDetailResultDto = JsonUtils.parseObject(accessCallBody, HlPayOrderDetailResultDto.class);
            AdInfoConfigDO adInfoConfigDO = adInfoService.queryConfigByAdId(adId);
            if (adInfoConfigDO == null) {
                return "fail";
            }
            if (!StringUtils.hasText(hlPayOrderDetailResultDto.getSign())) {
                log.warn("支付回调错误,签名为空");
                return "fail";
            }
            try {
                // 签名参数
                Map<String, Object> map = JSONUtil.toBean(accessCallBody, Map.class);
                boolean generateVerify = SignUtils.verify(map, adInfoConfigDO.getPublicKey());
                if (!generateVerify) {
                    return "fail";
                }
            }
            catch (Exception e) {
                e.printStackTrace();
                return "fail";
            }
            // 订单状态，0=支付失败，1=初始化，2=支付中，3=支付成功，4=已撤销，5=订单关闭
            if (!StringUtils.hasText(hlPayOrderDetailResultDto.getMch_order_no()) || !StringUtils.hasText(
                    hlPayOrderDetailResultDto.getState())) {
                log.warn("退款回调错误,订单状态 订单号为空,");
                return "fail";
            }
            PayOrderEnums.PAY_ORDER_STATUS payStatus = null;
            switch (hlPayOrderDetailResultDto.getState()) {
                case "0":
                    payStatus = PayOrderEnums.PAY_ORDER_STATUS.FAIL;
                    break;
                case "1":
                    payStatus = PayOrderEnums.PAY_ORDER_STATUS.INIT;
                    break;
                case "2":
                    payStatus = PayOrderEnums.PAY_ORDER_STATUS.PAYING;
                    break;
                case "3":
                    payStatus = PayOrderEnums.PAY_ORDER_STATUS.SUCCESS;
                    break;
                case "4":
                    payStatus = PayOrderEnums.PAY_ORDER_STATUS.CANCEL;
                    break;
                case "5":
                    payStatus = PayOrderEnums.PAY_ORDER_STATUS.CLOSE;
                    break;
            }
            if (payStatus == null) {
                log.warn("支付回调错误,支付状态错误 state:{}", hlPayOrderDetailResultDto.getState());
                return "fail";
            }
            log.info("订单号！！！mchOrderNo:{}", hlPayOrderDetailResultDto.getMch_order_no());
            AdPayOrderDO payOrderDO = adPayOrderService.queryDetailCache(hlPayOrderDetailResultDto.getMch_order_no());
            if (payOrderDO == null) {
                log.warn("支付回调错误,订单状态 订单号不存在,:{}", hlPayOrderDetailResultDto.getMch_order_no());
                return "fail";
            }
            if (payStatus.getCode().equals(payOrderDO.getState())) {
                return "success";
            }
            AdPayOrderDO updatePayOrderDO = new AdPayOrderDO();
            updatePayOrderDO.setId(payOrderDO.getId());
            updatePayOrderDO.setState(payStatus.getCode());
            updatePayOrderDO.setInsOrderNo(hlPayOrderDetailResultDto.getIns_order_sn());
            updatePayOrderDO.setChannelOrderNo(hlPayOrderDetailResultDto.getChannel_order_sn());
            if (hlPayOrderDetailResultDto.getAmount() != null) {
                updatePayOrderDO.setPayAmount(new BigDecimal(hlPayOrderDetailResultDto.getAmount()));
                payOrderDO.setPayAmount(updatePayOrderDO.getPayAmount());
            }
            // updatePayOrderDO.setRemark(hlPayOrderDetailResultDto.get());
            if (hlPayOrderDetailResultDto.getSuccess_time() != null) {
                updatePayOrderDO.setSuccessTime(Long.valueOf(hlPayOrderDetailResultDto.getSuccess_time()) * 1000l);
            }
            adPayOrderService.updatePayOrder(payOrderDO.getMchOrderNo(), updatePayOrderDO);
            switch (payStatus) {
                case SUCCESS:
                    adPayOrderHandler.paySuccess(payOrderDO);
                    break;
            }
            return "success";
        }
        catch (Exception e) {
            log.error("orderStatusCallBack error:{}", e.getMessage(),e);
            return "fail";
        }
    }

    @Override
    public String refundCallBack(Long adId, String accessCallBody) {
        log.info("refundCallBack adId:{},accessCallBody:{}", adId, accessCallBody);
        try {
            AdInfoConfigDO adInfoConfigDO = adInfoService.queryConfigByAdId(adId);
            if (adInfoConfigDO == null) {
                return "fail";
            }
            HlRefundOrderDetailResultDto hlRefundOrderDetailResultDto = JsonUtils.parseObject(accessCallBody, HlRefundOrderDetailResultDto.class);
            if (!StringUtils.hasText(hlRefundOrderDetailResultDto.getSign())) {
                log.warn("支付回调错误,签名为空");
                return "fail";
            }
            try {
                // 签名参数
                Map<String, Object> map = JSONUtil.toBean(accessCallBody, Map.class);
                boolean generateVerify = SignUtils.verify(map, adInfoConfigDO.getPublicKey());
                if (!generateVerify) {
                    return "fail";
                }
            }
            catch (Exception e) {
                return "fail";
            }
            // 退款状态，0=退款失败，1=初始化，2=退款中，3=退款成功，
            if (!StringUtils.hasText(hlRefundOrderDetailResultDto.getMch_refund_no()) || !StringUtils.hasText(
                    hlRefundOrderDetailResultDto.getState())) {
                log.warn("退款回调错误,订单状态 订单号为空,");
                return "fail";
            }
            PayOrderEnums.REFUND_STATUS refundStatus = null;
            PayOrderEnums.ORDER_REFUND_STATUS orderRefundStatus = null;
            switch (hlRefundOrderDetailResultDto.getState()) {
                case "0":
                    refundStatus = PayOrderEnums.REFUND_STATUS.FAIL;
                    orderRefundStatus = PayOrderEnums.ORDER_REFUND_STATUS.FAIL;
                    break;
                case "1":
                    refundStatus = PayOrderEnums.REFUND_STATUS.INIT;
                    break;
                case "2":
                    refundStatus = PayOrderEnums.REFUND_STATUS.REFUNDING;
                    break;
                case "3":
                    refundStatus = PayOrderEnums.REFUND_STATUS.REFUND;
                    orderRefundStatus = PayOrderEnums.ORDER_REFUND_STATUS.REFUND;
                    break;
            }
            if (refundStatus == null) {
                log.warn("退款回调错误,退款状态错误 state:{}", hlRefundOrderDetailResultDto.getState());
                return "fail";
            }
            log.info("订单号！！！refundOrderNo:{}", hlRefundOrderDetailResultDto.getMch_refund_no());
            AdRefundOrderDO adRefundOrderDO = adRefundOrderService.queryDetail(hlRefundOrderDetailResultDto.getMch_refund_no());
            if (adRefundOrderDO == null) {
                log.warn("退款回调错误,订单状态 订单号不存在 refundOrderNo:{}", hlRefundOrderDetailResultDto.getMch_refund_no());
                return "fail";
            }
            if (refundStatus.getCode().equals(adRefundOrderDO.getRefundStatus())) {
                return "success";
            }
            AdRefundOrderDO updateRefundOrderDO = new AdRefundOrderDO();
            updateRefundOrderDO.setId(adRefundOrderDO.getId());
            updateRefundOrderDO.setPlatRefundOrderNo(hlRefundOrderDetailResultDto.getPay_order_id());
            updateRefundOrderDO.setRefundStatus(refundStatus.getCode());
            updateRefundOrderDO.setRemark(hlRefundOrderDetailResultDto.getRefund_reason());
            updateRefundOrderDO.setSuccessTime(Long.valueOf(hlRefundOrderDetailResultDto.getSuccess_time()) * 1000l);
            adRefundOrderService.updateRefundOrder(adRefundOrderDO.getRefundOrderNo(), adRefundOrderDO.getRefundApplyNo(), updateRefundOrderDO);
            if (orderRefundStatus != null) {
                AdPayOrderDO payOrderDO = adPayOrderService.queryDetailCache(adRefundOrderDO.getMchOrderNo());
                if (orderRefundStatus.getCode().equals(PayOrderEnums.ORDER_REFUND_STATUS.REFUND.getCode())) {
                    if (payOrderDO.getPayAmount().compareTo(payOrderDO.getRefundAmount()) > 0) {
                        orderRefundStatus = PayOrderEnums.ORDER_REFUND_STATUS.PART_REFUND;
                    }
                }
                AdPayOrderDO updatePayOrderDO = new AdPayOrderDO();
                updatePayOrderDO.setId(payOrderDO.getId());
                updatePayOrderDO.setRefundStatus(orderRefundStatus.getCode());
                adPayOrderService.updatePayOrder(payOrderDO.getMchOrderNo(), updatePayOrderDO);
            }
            return "success";
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("refundCallBack error:{}", e.getMessage(),e);
            return "fail";
        }
    }

    @Override
    public String rechargeCallBack(Long adId, Map<String, Object> params) {
        log.info("rechargeCallBack adId:{},accessCallBody:{}", adId, JsonUtils.toJsonString(params));
        try {
            AdInfoConfigDO adInfoConfigDO = adInfoService.queryConfigByAdId(adId);
            if (adInfoConfigDO == null) {
                return "fail";
            }
            String sign = params.get("sign").toString();

            if (!StringUtils.hasText(sign)) {
                log.warn("充值回调错误,签名为空");
                return "fail";
            }
            try {
                AdOtherConfigDto otherConfigDto = adInfoConfigDO.getOtherConfigDto();
                String signMd5 = SignUtils.signIncludeNullMd5(params, otherConfigDto.getAppKey());
                if (!signMd5.toUpperCase().equals(sign)) {
                    return "fail";
                }
            }
            catch (Exception e) {
                return "fail";
            }
            String chargeNo = params.get("out_trade_num").toString();
            String state = params.get("state").toString();
            // 退款状态，0=退款失败，1=初始化，2=退款中，3=退款成功，
            if (!StringUtils.hasText(chargeNo) || !StringUtils.hasText(state)) {
                log.warn("充值回调错误,订单状态 订单号为空,");
                return "fail";
            }
            UserEnum.RECHARGE_STATUS rechargeStatus = null;
            // 1充值成功 ，2充值失败
            switch (state) {
                case "1":
                    rechargeStatus = UserEnum.RECHARGE_STATUS.SUCCESS;
                    break;
                case "2":
                    rechargeStatus = UserEnum.RECHARGE_STATUS.FAIL;
                    break;
            }
            if (rechargeStatus == null) {
                log.warn("充值回调错误,充值状态错误 state:{}", state);
                return "fail";
            }
            log.info("充值订单号！！！chargeNo:{}", chargeNo);
            UserTeleChargeOrderDO userTeleChargeOrderDO = userRechargeService.queryDetail(chargeNo);
            if (userTeleChargeOrderDO == null) {
                log.warn("充值回调错误,订单状态 订单号不存在 chargeNo:{}", chargeNo);
                return "fail";
            }
            if (rechargeStatus.getCode().toString().equals(state)) {
                return "success";
            }
            UserTeleChargeOrderDO updateRefundOrderDO = new UserTeleChargeOrderDO();
            updateRefundOrderDO.setId(userTeleChargeOrderDO.getId());
            updateRefundOrderDO.setState(rechargeStatus.getCode());
            userRechargeService.updateChargeOrder(updateRefundOrderDO);
            return "success";
        }
        catch (Exception e) {
            e.printStackTrace();
            log.error("rechargeCallBack error:{}", e.getMessage(),e);
            return "fail";
        }
    }
}
